// 市场数据服务
export interface MarketDataService {
  getOrderBook(symbol: string): Promise<OrderBookData>;
  getKlineData(symbol: string, interval: string, limit?: number): Promise<KlineData[]>;
  get24hrStats(symbol: string): Promise<TickerStats>;
  subscribeTicker(symbol: string, callback: (data: TickerData) => void): () => void;
  subscribeOrderBook(symbol: string, callback: (data: OrderBookData) => void): () => void;
}

export interface OrderBookData {
  symbol: string;
  bids: [string, string][]; // [price, quantity]
  asks: [string, string][];
  lastUpdateId: number;
}

export interface KlineData {
  openTime: number;
  open: string;
  high: string;
  low: string;
  close: string;
  volume: string;
  closeTime: number;
  quoteAssetVolume: string;
  numberOfTrades: number;
}

export interface TickerStats {
  symbol: string;
  priceChange: string;
  priceChangePercent: string;
  weightedAvgPrice: string;
  prevClosePrice: string;
  lastPrice: string;
  bidPrice: string;
  askPrice: string;
  openPrice: string;
  highPrice: string;
  lowPrice: string;
  volume: string;
  quoteVolume: string;
  openTime: number;
  closeTime: number;
  count: number;
}

export interface TickerData {
  symbol: string;
  price: string;
  time: number;
}

// Binance API 实现
export class BinanceMarketDataService implements MarketDataService {
  private baseUrl = 'https://api.binance.com/api/v3';
  private wsBaseUrl = 'wss://stream.binance.com:9443/ws';
  private connections: Map<string, WebSocket> = new Map();

  async getOrderBook(symbol: string): Promise<OrderBookData> {
    try {
      const response = await fetch(`${this.baseUrl}/depth?symbol=${symbol.toUpperCase()}&limit=100`);
      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }
      const data = await response.json();
      return {
        symbol: symbol,
        bids: data.bids,
        asks: data.asks,
        lastUpdateId: data.lastUpdateId,
      };
    } catch (error) {
      console.error('Error fetching order book:', error);
      throw error;
    }
  }

  async getKlineData(symbol: string, interval: string = '1h', limit: number = 100): Promise<KlineData[]> {
    try {
      const response = await fetch(
        `${this.baseUrl}/klines?symbol=${symbol.toUpperCase()}&interval=${interval}&limit=${limit}`
      );
      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }
      const data = await response.json();
      return data.map((kline: number[]) => ({
        openTime: kline[0],
        open: kline[1],
        high: kline[2],
        low: kline[3],
        close: kline[4],
        volume: kline[5],
        closeTime: kline[6],
        quoteAssetVolume: kline[7],
        numberOfTrades: kline[8],
      }));
    } catch (error) {
      console.error('Error fetching kline data:', error);
      throw error;
    }
  }

  async get24hrStats(symbol: string): Promise<TickerStats> {
    try {
      const response = await fetch(`${this.baseUrl}/ticker/24hr?symbol=${symbol.toUpperCase()}`);
      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }
      return await response.json();
    } catch (error) {
      console.error('Error fetching 24hr stats:', error);
      throw error;
    }
  }

  subscribeTicker(symbol: string, callback: (data: TickerData) => void): () => void {
    const streamName = `${symbol.toLowerCase()}@ticker`;
    const ws = new WebSocket(`${this.wsBaseUrl}/${streamName}`);
    
    ws.onmessage = (event) => {
      try {
        const data = JSON.parse(event.data);
        callback({
          symbol: data.s,
          price: data.c,
          time: data.E,
        });
      } catch (error) {
        console.error('Error parsing ticker data:', error);
      }
    };

    ws.onerror = (error) => {
      console.error('WebSocket error:', error);
    };

    this.connections.set(streamName, ws);

    // 返回取消订阅函数
    return () => {
      if (ws.readyState === WebSocket.OPEN) {
        ws.close();
      }
      this.connections.delete(streamName);
    };
  }

  subscribeOrderBook(symbol: string, callback: (data: OrderBookData) => void): () => void {
    const streamName = `${symbol.toLowerCase()}@depth@100ms`;
    const ws = new WebSocket(`${this.wsBaseUrl}/${streamName}`);
    
    ws.onmessage = (event) => {
      try {
        const data = JSON.parse(event.data);
        callback({
          symbol: data.s,
          bids: data.b,
          asks: data.a,
          lastUpdateId: data.u,
        });
      } catch (error) {
        console.error('Error parsing order book data:', error);
      }
    };

    ws.onerror = (error) => {
      console.error('WebSocket error:', error);
    };

    this.connections.set(streamName, ws);

    // 返回取消订阅函数
    return () => {
      if (ws.readyState === WebSocket.OPEN) {
        ws.close();
      }
      this.connections.delete(streamName);
    };
  }

  // 清理所有连接
  disconnect(): void {
    this.connections.forEach((ws) => {
      if (ws.readyState === WebSocket.OPEN) {
        ws.close();
      }
    });
    this.connections.clear();
  }
}

// CoinGecko API 实现（免费，但功能有限）
export class CoinGeckoMarketDataService {
  private baseUrl = 'https://api.coingecko.com/api/v3';

  async getPrice(coinId: string): Promise<Record<string, unknown>> {
    try {
      const response = await fetch(
        `${this.baseUrl}/simple/price?ids=${coinId}&vs_currencies=usd&include_24hr_change=true&include_24hr_vol=true`
      );
      return await response.json();
    } catch (error) {
      console.error('Error fetching price from CoinGecko:', error);
      throw error;
    }
  }

  async getMarketChart(coinId: string, days: number = 7): Promise<Record<string, unknown>> {
    try {
      const response = await fetch(
        `${this.baseUrl}/coins/${coinId}/market_chart?vs_currency=usd&days=${days}`
      );
      return await response.json();
    } catch (error) {
      console.error('Error fetching market chart from CoinGecko:', error);
      throw error;
    }
  }
}

// 模拟数据服务（用于开发和测试）
export class MockMarketDataService implements MarketDataService {
  async getOrderBook(symbol: string): Promise<OrderBookData> {
    // 生成模拟订单簿数据
    const basePrice = 62350;
    const bids: [string, string][] = [];
    const asks: [string, string][] = [];

    for (let i = 0; i < 20; i++) {
      const bidPrice = (basePrice - (i + 1) * 25).toFixed(2);
      const bidQuantity = (Math.random() * 2 + 0.1).toFixed(6);
      bids.push([bidPrice, bidQuantity]);

      const askPrice = (basePrice + (i + 1) * 25).toFixed(2);
      const askQuantity = (Math.random() * 2 + 0.1).toFixed(6);
      asks.push([askPrice, askQuantity]);
    }

    return {
      symbol,
      bids,
      asks,
      lastUpdateId: Date.now(),
    };
  }

  async getKlineData(_symbol: string, _interval?: string, limit: number = 100): Promise<KlineData[]> {
    const data: KlineData[] = [];
    let basePrice = 62350;
    const now = Date.now();

    for (let i = limit; i >= 0; i--) {
      const openTime = now - i * 60 * 60 * 1000; // 1小时间隔
      const open = basePrice + (Math.random() - 0.5) * 1000;
      const high = open + Math.random() * 500;
      const low = open - Math.random() * 500;
      const close = low + Math.random() * (high - low);
      const volume = (Math.random() * 1000 + 100).toFixed(6);

      data.push({
        openTime,
        open: open.toFixed(2),
        high: high.toFixed(2),
        low: low.toFixed(2),
        close: close.toFixed(2),
        volume,
        closeTime: openTime + 60 * 60 * 1000 - 1,
        quoteAssetVolume: (parseFloat(volume) * close).toFixed(2),
        numberOfTrades: Math.floor(Math.random() * 1000) + 100,
      });

      basePrice = close;
    }

    return data;
  }

  async get24hrStats(symbol: string): Promise<TickerStats> {
    const lastPrice = 62350 + (Math.random() - 0.5) * 2000;
    const openPrice = lastPrice * (1 + (Math.random() - 0.5) * 0.1);
    const priceChange = lastPrice - openPrice;
    const priceChangePercent = ((priceChange / openPrice) * 100).toFixed(2);

    return {
      symbol,
      priceChange: priceChange.toFixed(2),
      priceChangePercent,
      weightedAvgPrice: lastPrice.toFixed(2),
      prevClosePrice: openPrice.toFixed(2),
      lastPrice: lastPrice.toFixed(2),
      bidPrice: (lastPrice - 10).toFixed(2),
      askPrice: (lastPrice + 10).toFixed(2),
      openPrice: openPrice.toFixed(2),
      highPrice: (Math.max(lastPrice, openPrice) + 500).toFixed(2),
      lowPrice: (Math.min(lastPrice, openPrice) - 500).toFixed(2),
      volume: (Math.random() * 10000 + 1000).toFixed(2),
      quoteVolume: (Math.random() * 100000000 + 10000000).toFixed(2),
      openTime: Date.now() - 24 * 60 * 60 * 1000,
      closeTime: Date.now(),
      count: Math.floor(Math.random() * 100000) + 10000,
    };
  }

  subscribeTicker(symbol: string, callback: (data: TickerData) => void): () => void {
    const interval = setInterval(() => {
      const price = 62350 + (Math.random() - 0.5) * 2000;
      callback({
        symbol,
        price: price.toFixed(2),
        time: Date.now(),
      });
    }, 1000);

    return () => clearInterval(interval);
  }

  subscribeOrderBook(symbol: string, callback: (data: OrderBookData) => void): () => void {
    const interval = setInterval(async () => {
      const orderBook = await this.getOrderBook(symbol);
      callback(orderBook);
    }, 500);

    return () => clearInterval(interval);
  }
}

// 数据服务工厂
export function createMarketDataService(type: 'binance' | 'coingecko' | 'mock' = 'mock'): MarketDataService {
  switch (type) {
    case 'binance':
      return new BinanceMarketDataService();
    case 'mock':
    default:
      return new MockMarketDataService();
  }
}
